﻿#region Librerias

using System;
using System.Deployment.Application;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows;
using System.Windows.Input;
using ESF.General;
using ESF.SFT.FileUploader.Config;
using ESF.SFT.FileUploader.Helpers;
using Microsoft.Win32;
using System.Diagnostics;
using ESF.WinForms;
using ESF.SFT.FileUploader.SharedResources;
using ESF.WinForms.Elements;
using System.Security.Cryptography.X509Certificates;
using ESF.General.Entity;
using System.Windows.Controls;

#endregion


namespace ESF.SFT.FileUploader
{
	/// <summary>
	/// Interaction logic for ConfigureDigitalFileSign.xaml
	/// </summary>
	public partial class ConfigureDigitalFileSign : BaseWPFWindow
	{
		#region Events

		public delegate void Changing (DigitalFileSignConfig pConfigChanged);
		
		public event Changing Changed; 

		#endregion


		#region Constantes

		private const string PARTCONFNAME = "_cer.cfg";

		#endregion


		#region Propiedades

		public DigitalFileSignConfig Config
		{
			private set
			{
				int i;
				

				if (value == null)
				{
					rblWithoutSign.IsChecked = true;
					rblWithCer.IsChecked = false;
					
					return;
				}

				if (rblWithCer.IsEnabled)
				{				
					rblWithCer.IsChecked = value.UseCER;
					rblWithoutSign.IsChecked = value.UseNothing;
				}
				else
				{
					rblWithCer.IsChecked = false;
					rblWithoutSign.IsChecked = true;
				}

				LoadCertificateList ();

				i = 0;

				if (value.UseCER)
				{
					foreach (CertificateResumen cerres in ddlCertificateList.ItemsSource)
					{
						if (cerres.Thumbprint == value.CERTumbprint && cerres.FromFile == value.FromFile)
						{
							ddlCertificateList.SelectedIndex = i;

							ddlCertificateList.ScrollIntoView (ddlCertificateList.SelectedItem);

							break;
						}

						i++;
					}

					if (ddlCertificateList.SelectedIndex == -1)
					{
						frmInfoMsg = "El certificado configurado no esta disponible (si es de token conectelo) o seleccione otro";
						return;
					}

					X509Certificate2 certificate;
						
						
					certificate = DigitalSignHelper.GetCertificate (value.CERTumbprint);
						
					if (certificate != null)
					{
						if (!certificate.Verify ())
						{
							frmInfoMsg = "El archivo del certificado configurado es invalido";
							return;
						}
					}
					else
					{
						frmInfoMsg = "El archivo del certificado indicado no esta registrado";
						return;
					}
				}

				Changed (value);
			}
			get
			{
				if (rblWithoutSign.IsChecked == true && rblWithoutSign.IsEnabled == false)
				{
					throw new GenericInfoException ("Se requiere que configure un certificado digital para firmar los archivos para poder enviarlos");
				}
				
				return new DigitalFileSignConfig () 
				{
					CERTumbprint = (ddlCertificateList.SelectedItem == null ? string.Empty : (ddlCertificateList.SelectedItem as CertificateResumen).Thumbprint),
					FromFile = (ddlCertificateList.SelectedItem == null ? false : (ddlCertificateList.SelectedItem as CertificateResumen).FromFile)
				};
			}
		}


		public CertificateResumen SelectedCertificateResumen
		{
			get
			{
				return Dispatcher.Invoke ((Func<CertificateResumen>) (() => 
				{
					if (ddlCertificateList.SelectedItem == null)
					{
						return null;
					}
				
					return (ddlCertificateList.SelectedItem as CertificateResumen);
				})) as CertificateResumen;
			}
		}


		public X509Certificate2 SelectedCertificate
		{
			get
			{
				if (SelectedCertificateResumen == null)
				{
					return null;
				}

				return SelectedCertificateResumen.Certificate;
			}
		}

		#endregion


		#region Constructor

		public ConfigureDigitalFileSign()
			: base()
		{
			InitializeComponent();

			Icon = WinFormsHelper.ToBitmapSource(SharedImages.Upload_64x64);

			imgIcon.Source = WinFormsHelper.ToBitmapSource (SharedResources.SharedImages.Certificate_64x64);


			LoadCertificateList ();
			
			IncludeVersionInTitle();
		}

		#endregion


		#region Funciones

		private void LoadCertificateList ()
		{
			System.Collections.Generic.List<CertificateResumen> certificates;


			certificates = DigitalSignHelper.ListUserCertificatesResumen().FindAll (cr => 
					TextHelper.IsIn (cr.IssuerName_CN, 
						TextHelper.Split ('|', Program.Conf.Find (c => c.Key == "CertificationAuthorities").Value)));

			ddlCertificateList.ItemsSource = certificates;
		}


		public void ShowHtmlHelp (string pHtmlHelpContents)
		{
			// TODO: Soportarlo
		}


		public void LoadConfiguration ()
		{
			bool pRequiresDigitalCertificate = false;

			
			rblWithoutSign.IsChecked = !pRequiresDigitalCertificate;
			rblWithoutSign.IsEnabled = !pRequiresDigitalCertificate;
			rblWithoutSign.Visibility = pRequiresDigitalCertificate ? Visibility.Hidden : Visibility.Visible;

			Config = SerializeHelper.DeSerializeFromFileBin<DigitalFileSignConfig> (Log.GenerateFileName(Log.Session_UserName, PARTCONFNAME));
		}


		private bool SaveConfiguration ()
		{
			DigitalFileSignConfig config;

			string configFileName;


			if (rblWithCer.IsChecked.Value && ddlCertificateList.SelectedIndex == -1)
			{
				MessageBox.Show (this, "Seleccione un Certificado Digital para utilizarlo", "Revise lo siguiente", MessageBoxButton.OK, MessageBoxImage.Question);
				return false;
			}


			configFileName = Log.GenerateFileName (Log.Session_UserName, PARTCONFNAME);

			FileHelper.Delete (configFileName);

			config = Config;

			using (FileStream FS = new FileStream (configFileName, FileMode.Create))
			{
				new BinaryFormatter ().Serialize (FS, config);
			}

			File.SetAttributes (configFileName, FileAttributes.Hidden);

			if (Changed != null)
			{
				Changed (config);
			}

			return true;
		}


		private void ClearTexts ()
		{
			if (ddlCertificateList == null) { return; }

			ddlCertificateList.IsEnabled = false;
			ddlCertificateList.SelectedIndex = -1;
		}


		internal string SignFile (string pOriginalFileName, string pOriginalFileDescription, string pFileName, bool pDeleteFile)
		{
			if (!Config.UseCER) { return pFileName; }

			return DigitalSignHelper.SignFile(pOriginalFileName, pOriginalFileDescription, pFileName, Config.CERTumbprint, pDeleteFile);
		}

		#endregion


		#region RadioButton Events

		private void rblWithoutSign_Checked(object sender, RoutedEventArgs e)
		{
			ClearTexts();
		}

		private void rblWithCer_Checked(object sender, RoutedEventArgs e)
		{
			ClearTexts();

			if (ddlCertificateList != null)
			{
				ddlCertificateList.IsEnabled = true;
			}
		}

		#endregion


		#region Button Events

		private void btnSave_Click(object sender, RoutedEventArgs e)
		{
			if (SaveConfiguration ())
			{
				Hide();
			}
		}

		#endregion

		
		#region Window Events

		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			if (IsVisible)
			{
				MessageBox.Show (this, "Los cambios realizados han sido ignorados", "Cambios ignorados", MessageBoxButton.OK, MessageBoxImage.Exclamation);

				e.Cancel = true;

				LoadConfiguration ();
			
				Hide ();
			}
		}

		#endregion


		private void btnRefreshList_Click(object sender, RoutedEventArgs e)
		{
			LoadCertificateList ();

			ddlCertificateList.Focus ();

			frmInfoMsg = "Seleccione el Certificado Digital de la lista y luego de click en \"Guardar la Selección\"";
		}
	}
}
